package com.ruyiadmin.springboot.web_api.aspects.system;

import com.alibaba.fastjson.JSON;
import com.ruyiadmin.springboot.web_api.annotations.system.OperationLog;
import com.ruyiadmin.springboot.common_infrastructure.awares.framework.RuYiApplicationContextAware;
import com.ruyiadmin.springboot.common_infrastructure.events.business.SysLogEvent;
import com.ruyiadmin.springboot.service_layer.components.business.OperationLogContext;
import com.ruyiadmin.springboot.common_infrastructure.classes.SysLog;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * <p>
 * 系统日志切面定义
 * </p>
 *
 * @author RuYiAdmin
 * @since 2022-07-20
 */
@Component
@Aspect
@Slf4j
@RequiredArgsConstructor
public class OperationLogAspect {

    private final OperationLogContext logContext;

    @Around("@annotation(operationLog)")
    @SneakyThrows
    public Object around(ProceedingJoinPoint point, OperationLog operationLog) {

        SysLog log = logContext.getSysLog();

        log.setOperationType(operationLog.operationType().ordinal());
        if (!StringUtils.isEmpty(operationLog.description())) {
            log.setRemark(operationLog.description());
        }

        if (point.getArgs().length > 0) {
            try {
                log.setParams(JSON.toJSONString(point.getArgs()));
            } catch (Exception e) {
                e.printStackTrace();
                log.setParams(Arrays.toString(point.getArgs()));
            }
        }

        //Long startTime = System.currentTimeMillis();
        Object obj;
        try {
            obj = point.proceed();
            log.setResult(JSON.toJSONString(obj));
        } catch (Exception e) {
            throw e;
        } finally {
            //Long endTime = System.currentTimeMillis();
            // 发送异步日志事件
            RuYiApplicationContextAware.publishEvent(new SysLogEvent(log));
        }

        return obj;
    }

}
